Skip to content

Add Bookings ft#7

Merged
Sitaras merged 30 commits intomainfrom
bookings
Nov 23, 2025
Merged

Add Bookings ft#7
Sitaras merged 30 commits intomainfrom
bookings

Conversation

@XxcuriousxX
Copy link
Collaborator

Implemented booking creation

@Sitaras Sitaras requested a review from Copilot November 2, 2025 21:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a booking system that allows passengers to create bookings for available routes. The implementation includes type definitions, validation schemas, database models, API routes, and controller logic for handling booking creation.

  • Introduces booking creation functionality with validation and business logic
  • Adds TypeScript types and Mongoose models for bookings
  • Integrates booking routes into the main router

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
back-end/src/types/booking.types.ts Defines TypeScript interface for booking entities with passenger, driver, route references and status
back-end/src/schemas/bookingSchema.ts Defines Zod validation schemas for booking operations and queries
back-end/src/routes/index.ts Registers booking routes in the main application router
back-end/src/routes/booking.routes.ts Defines the booking API endpoint for creating bookings
back-end/src/models/route.model.ts Exports IRouteDocument interface and updates model type for better type safety
back-end/src/models/booking.model.ts Implements Mongoose schema and model for booking documents
back-end/src/controllers/booking.controller.ts Implements booking creation logic with validation and business rules

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Sitaras Sitaras requested a review from Copilot November 9, 2025 00:51
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 41 out of 45 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • back-end/package-lock.json: Language not supported
Comments suppressed due to low confidence (5)

back-end/src/controllers/ride.controller.ts:1

  • The Booking import is not used anywhere in this file and should be removed.
    back-end/src/models/ride.model.ts:119
  • The commented-out lines reference "routeSchema" but should be removed entirely or updated to reference "rideSchema" if they're intended to be uncommented in the future.
    back-end/src/controllers/ride.controller.ts:1
  • Unused import Booking.
    back-end/src/controllers/ride.controller.ts:12
  • Unused import Types.
    back-end/src/routes/user.routes.ts:6
  • Unused import RideController.
import { RideController } from "../controllers/ride.controller";

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to 20
if (ref.current) observer.observe(ref.current);

return () => {
if (element) observer.unobserve(element);
if (ref.current) observer.unobserve(ref.current);
};
Copy link

Copilot AI Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup function in the useEffect may reference a stale ref.current value. When the component unmounts, ref.current might already be null, causing the observer to not properly unobserve the element. Store the current element in a variable within the effect to ensure proper cleanup.

useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
    const target = entries[0];
    if (target.isIntersecting) {
      callback?.();
    }
  });

  const element = ref.current;
  if (element) observer.observe(element);

  return () => {
    if (element) observer.unobserve(element);
  };
}, [callback]);

Copilot uses AI. Check for mistakes.
if (ref.current) observer.unobserve(ref.current);
};
}, []);
}, [callback]);
Copy link

Copilot AI Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback dependency in the useEffect will cause the IntersectionObserver to be recreated every time the callback changes, which could be on every render if the callback is not memoized. This can lead to performance issues and unexpected behavior. Consider using a ref to store the callback or removing it from the dependency array if the callback doesn't need to trigger observer recreation.

Copilot uses AI. Check for mistakes.
@Sitaras Sitaras requested a review from Copilot November 9, 2025 17:01
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 42 out of 46 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • back-end/package-lock.json: Language not supported
Comments suppressed due to low confidence (3)

front-end/src/app/(home)/ride/[...slug]/page.tsx:90

  • The string concatenation rideData.driverProfile.rating.count + "rides" produces output like "5rides" without a space. This should be ${rideData.driverProfile.rating.count} rides or include a space in the string to produce readable output like "5 rides".
    back-end/src/controllers/ride.controller.ts:1
  • Unused import Booking.
    back-end/src/controllers/ride.controller.ts:12
  • Unused import Types.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +40 to +45
* @route GET /api/ride/all
* @desc Get all rides
* @access Public
*/
router.get(
"/all",
Copy link

Copilot AI Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API endpoint ride/all is inconsistent with the RESTful design pattern used elsewhere. The old endpoint was /routes (GET all routes), and the new endpoint should simply be /ride for consistency, not /ride/all.

This creates confusion since POST /ride creates a ride, but GET requires /ride/all to list rides. The /all suffix is redundant - a GET request to /ride without an ID parameter should naturally return all rides.

Suggested change
* @route GET /api/ride/all
* @desc Get all rides
* @access Public
*/
router.get(
"/all",
* @route GET /api/ride
* @desc Get all rides
* @access Public
*/
router.get(
"/",

Copilot uses AI. Check for mistakes.
@Sitaras Sitaras requested a review from Copilot November 9, 2025 18:33
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 50 out of 54 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • back-end/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sitaras and others added 2 commits November 9, 2025 20:38
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Sitaras Sitaras requested a review from Copilot November 9, 2025 18:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 50 out of 54 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • back-end/package-lock.json: Language not supported
Comments suppressed due to low confidence (2)

front-end/src/app/(home)/ride/[...slug]/page.tsx:90

  • There's a spacing issue in the string concatenation. The current code results in "(5rides )" with "rides" directly attached to the count. Add a space before "rides":
({rideData.driverProfile.rating.count} rides)

back-end/src/controllers/ride.controller.ts:7

  • Use relative import ../schemas/rideSchema instead of aliased import @/schemas/rideSchema for consistency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


try {
const response = await api
.url(`ride/all?${queryString}`)
Copy link

Copilot AI Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The API endpoint in the front-end uses /ride/all to fetch rides, but there's an inconsistency: the comment in the backend route says "Get all rides" but the actual endpoint likely expects query parameters for filtering (as seen in getRideQuerySchema). Consider renaming to /ride/search or /rides for better semantic clarity.

Suggested change
.url(`ride/all?${queryString}`)
.url(`rides?${queryString}`)

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 60 out of 64 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • back-end/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

front-end/src/app/(home)/ride/[...slug]/page.tsx:222

  • The isBookingAvailable prop is always set to true, but it should be calculated based on rideData.remainingSeats > 0. This means the booking button will always appear enabled even when there are no seats available.

Change to:

<BookingButton rideId={rideData._id} isBookingAvailable={rideData.remainingSeats > 0} />

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 91 to 105
state.queuedRequests.forEach(async ({ req }) => {
try {
const result = await req
return await req
.auth(`Bearer ${newToken}`)
.customError(
async (error: WretchError, response: WretchResponse) => {
return { ...error, json: await response.json() };
}
)
.fetch()
.json((json: { data: any }) => json?.data);
return result;
} catch (err) {
throw err;
}
});
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The queued requests replay logic doesn't handle the response properly. The return statement inside the forEach callback doesn't return from the main function, and there's no mechanism to resolve/reject promises for the queued requests. This means queued requests will hang indefinitely.

Consider implementing a proper queue with promise resolution:

state.queuedRequests.forEach(async ({ req, resolve, reject }) => {
  try {
    const result = await req
      .auth(`Bearer ${newToken}`)
      .customError(
        async (error: WretchError, response: WretchResponse) => {
          return { ...error, json: await response.json() };
        }
      )
      .fetch()
      .json((json: { data: any }) => json?.data);
    resolve?.(result);
  } catch (err) {
    reject?.(err);
  }
});

Copilot uses AI. Check for mistakes.
Comment on lines 12 to 15
const state = {
isRefreshingToken: false,
queuedRequests: new Map<string, { req: any }>(),
resolveRefreshPromise: null as ((token: string) => void) | null,
};
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolveRefreshPromise field was removed from the state object, but the queue management system is incomplete. The queued requests are stored but never properly resolved or rejected, which will cause those requests to hang indefinitely.

Copilot uses AI. Check for mistakes.
Comment on lines 12 to +21
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
const target = entries[0];
if (target.isIntersecting) {
callbackRef.current?.();
callback?.();
}
});

const element = ref.current;
if (element) observer.observe(element);
if (ref.current) observer.observe(ref.current);

return () => {
if (element) observer.unobserve(element);
if (ref.current) observer.unobserve(ref.current);
};
}, []);
}, [callback]);
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback dependency in the useEffect can cause the observer to be recreated on every render if the callback is not memoized by the parent component. This can lead to performance issues and unexpected behavior.

Consider using a ref to store the callback:

const callbackRef = useRef(callback);

useEffect(() => {
  callbackRef.current = callback;
}, [callback]);

useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
    const target = entries[0];
    if (target.isIntersecting) {
      callbackRef.current?.();
    }
  });

  const element = ref.current;
  if (element) observer.observe(element);

  return () => {
    if (element) observer.unobserve(element);
  };
}, []);

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 83 out of 87 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (3)

front-end/src/schemas/rideSchema.ts:46

  • The zod API for integer validation is incorrect. In zod v4, z.int() is not a standalone method. Use z.number().int() instead.

Change z.int("Available seats must be an integer") to z.number().int({ message: "Available seats must be an integer" }).
front-end/src/schemas/rideSchema.ts:81

  • The z.enum() requires an array, not an enum object. This will cause a runtime error.

Change z.enum(RideStatus) to z.nativeEnum(RideStatus) to work with TypeScript enums.
front-end/src/app/(home)/ride/[...slug]/page.tsx:219

  • The isBookingAvailable prop is always true in this call, but should be calculated based on the ride's remaining seats.

Change to: <BookingButton rideId={rideData._id} isBookingAvailable={rideData.remainingSeats > 0} />


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

import { z } from "zod";

export const getUserRidesQuerySchema = z.object({
type: z.enum(UserRideRole).prefault(UserRideRole.AS_PASSENGER).optional(),
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In zod v4, the error message property should be message not error. The error property is not a valid zod option and will be ignored or cause errors.

Change { error: "..." } to { message: "..." } for all validation error messages.

Copilot uses AI. Check for mistakes.
import { z } from "zod";

export const getUserRidesQuerySchema = z.object({
type: z.enum(UserRideRole).prefault(UserRideRole.AS_PASSENGER).optional(),
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The z.enum() method requires an array of values, not an enum object. This will cause a runtime error.

Change z.enum(UserRideRole) to z.enum([UserRideRole.AS_PASSENGER, UserRideRole.AS_DRIVER]) or z.nativeEnum(UserRideRole) if you want to use the TypeScript enum directly.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +33
email: z.email({
error: "emailError"
}).trim(),
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The z.email() method must be chained after z.string(). Using z.email() directly is not valid in zod.

Change to: z.string().email({ message: "emailError" }).trim()

Suggested change
email: z.email({
error: "emailError"
}).trim(),
email: z.string().email({ message: "emailError" }).trim(),

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
type: z.enum(UserRideRole).prefault(UserRideRole.AS_PASSENGER).optional(),
sortOrder: z.enum(["asc", "desc"]).prefault("asc").optional(),
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The zod schema API has changed incorrectly. In zod v4, the correct method is default() not prefault(). The method name prefault appears to be a typo and will cause runtime errors.

All occurrences of .prefault() should be changed to .default().

Copilot uses AI. Check for mistakes.
@@ -1,11 +1,11 @@
import { Request, Response, NextFunction } from "express";
import { z, ZodError } from "zod";
import { z, ZodError, ZodSchema } from "zod";
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import z.

Suggested change
import { z, ZodError, ZodSchema } from "zod";
import { ZodError, ZodSchema } from "zod";

Copilot uses AI. Check for mistakes.
sitarass and others added 8 commits November 17, 2025 01:27
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* logout feature

* refactor: code improvements

---------

Co-authored-by: sitaras <sitaras@thinkdesquared.com>
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
6.9% Duplication on New Code (required ≤ 3%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Sitaras Sitaras merged commit dfa0398 into main Nov 23, 2025
0 of 2 checks passed
@Sitaras Sitaras deleted the bookings branch November 23, 2025 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants